package com.terry.activity.service.impl;

import com.alibaba.fastjson.JSON;
import com.terry.activity.bean.EntryModel;
import com.terry.activity.bean.VoteModel;
import com.terry.activity.bean.constant.ActivityType;
import com.terry.activity.bean.exception.DataAlreadyExistException;
import com.terry.activity.bean.exception.DataNotExistException;
import com.terry.activity.dao.IEntryDao;
import com.terry.activity.dao.IVoteDao;
import com.terry.activity.service.IVoteService;
import com.terry.activity.util.CommonUtil;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.Resource;
import java.util.NoSuchElementException;

/**
 * Create On 18/4/25.
 *
 * @author TerrySolar
 */
@Service("voteService")
public class VoteServiceImpl implements IVoteService {

    @Resource
    private JedisPool jedisPool;

    @Resource
    private IVoteDao voteDao;

    @Resource
    private IEntryDao entryDao;

    @Override
    public boolean vote(Long entryId, String openId) throws DataAlreadyExistException, DataNotExistException {

        EntryModel entryModel;

        try {
            entryModel = this.entryDao.findById(entryId).get();
        } catch (NoSuchElementException e) {
            throw new DataNotExistException("投票作品不存在！");
        }

        Long activityId = entryModel.getActivityModel().getId();

        Jedis jedis = jedisPool.getResource();
        String redisKey;

        // 从缓存获取
        if (entryModel.getActivityModel().getType() == ActivityType.MANUAL_CATALOG) {
            redisKey = CommonUtil.GenerateRedisKey("vote:" + openId + ":" + activityId + ":" + entryModel.getCatalogModel().getId());
        } else {
            redisKey = CommonUtil.GenerateRedisKey("vote:" + openId + ":" + activityId);
        }

        if (jedis.get(redisKey) != null) {
            jedis.close();
            throw new DataAlreadyExistException("已经投过票了，请勿重复操作！");
        }

        VoteModel voteModel;

        if (entryModel.getActivityModel().getType() == ActivityType.MANUAL_CATALOG) {
            voteModel = this.retrieveVote(openId, activityId, entryModel.getCatalogModel().getId());
        } else {
            voteModel = this.retrieveVote(openId, activityId);
        }

        if (voteModel != null) {
            jedis.setex(redisKey, 60 * 60 * 24 * 2, JSON.toJSONString(voteModel));
            throw new DataAlreadyExistException("已经投过票了，请勿重复操作！");
        }

        voteModel = new VoteModel();
        voteModel.setEntryModel(entryModel);
        voteModel.setOpenId(openId);
        voteModel.setActivityModel(entryModel.getActivityModel());
        voteModel.setCatalogModel(entryModel.getCatalogModel());
        voteDao.save(voteModel);

        jedis.setex(redisKey, 60 * 60 * 24 * 2, JSON.toJSONString(voteModel));

        // 票数 + 1
        jedis.incr(CommonUtil.GenerateRedisKey("vote:" + "sum:" + entryModel.getId()));

        jedis.close();
        return true;
    }

    @Override
    public VoteModel retrieveVote(String openId, Long activityId) {
        return this.voteDao.findVoteModelByOpenIdAndActivityModel_Id(openId, activityId);
    }

    @Override
    public VoteModel retrieveVote(String openId, Long activityId, Long catalogId) {
        return this.voteDao.findByOpenIdAndActivityModel_IdAndCatalogModel_Id(openId, activityId, catalogId);
    }

    @Override
    public Integer retrieveVoteCount(Long entryId) {
        Jedis jedis = jedisPool.getResource();

        Integer voteCount = 0;

        // 先从缓存中读取, 无缓存则读库
        if (jedis.get(CommonUtil.GenerateRedisKey("vote:" + "sum:" + entryId)) != null) {
            voteCount = Integer.parseInt(jedis.get(CommonUtil.GenerateRedisKey("vote:" + "sum:" + entryId)));
        } else {
            voteCount = this.voteDao.countByEntryModel_Id(entryId);
            jedis.setex(CommonUtil.GenerateRedisKey("vote:" + "sum:" + entryId), 60 * 60 * 24, String.valueOf(voteCount));
        }

        jedis.close();

        return voteCount;
    }

}
